package com.aloda.scoring;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.aloda.constant.ErrorCode;
import com.aloda.constant.ExceptionConstant;
import com.aloda.dto.QuestionAndResultListDTO;
import com.aloda.dto.ScoreAndScoringResultDTO;
import com.aloda.dto.question.QuestionContentDTO;
import com.aloda.entity.App;
import com.aloda.entity.Question;
import com.aloda.entity.ScoringResult;
import com.aloda.exception.BaseException;
import com.aloda.exception.WarnException;
import com.aloda.mapper.QuestionMapper;
import com.aloda.mapper.ScoringResultMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 对选项和应用对应数据进行处理
 */
@Component
public class DataTreating {

    @Resource
    private ScoringResultMapper scoringResultMapper;

    @Resource
    private QuestionMapper questionMapper;

    /**
     * 获取题目和评分结果列表
     * @param choices 用户选项集合
     * @param app 应用
     * @return 题目和评分结果列表
     */
    public QuestionAndResultListDTO getQuestionAndResult(List<String> choices, App app) {
        // 参数校验
        if (choices.isEmpty()) {
            throw new WarnException(ErrorCode.PARAMS_ERROR);
        }
        if (BeanUtil.isEmpty(app)) {
            throw new WarnException(ErrorCode.PARAMS_ERROR);
        }

        // 2.取出app对应的题目和所有评分结果
        LambdaQueryWrapper<Question> questionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        questionLambdaQueryWrapper.eq(Question::getAppId, app.getId());
        Question question = questionMapper.selectOne(questionLambdaQueryWrapper);
        if (BeanUtil.isEmpty(question)) {
            throw new BaseException(ExceptionConstant.QUESTION_NOT_EXIST);
        }
        LambdaQueryWrapper<ScoringResult> scoringResultLambdaQueryWrapper = new LambdaQueryWrapper<>();
        scoringResultLambdaQueryWrapper.eq(ScoringResult::getAppId, app.getId())
                .orderByDesc(ScoringResult::getResultScoreRange);
        List<ScoringResult> scoringResultList = scoringResultMapper.selectList(scoringResultLambdaQueryWrapper);
        if (scoringResultList.isEmpty()) {
            throw new BaseException(ExceptionConstant.RESULT_NOT_EXIST);
        }
        QuestionAndResultListDTO questionAndResultListDTO = new QuestionAndResultListDTO();
        questionAndResultListDTO.setQuestion(question);
        questionAndResultListDTO.setScoringResultList(scoringResultList);
        return questionAndResultListDTO;
    }

    /**
     * 获取用户的分数对应的评分结果
     * @param question 题目
     * @param choices 选项列表
     * @param scoringResultList 评分结果列表
     * @return
     */
    public ScoreAndScoringResultDTO getUserScoreRange(Question question, List<String> choices, List<ScoringResult> scoringResultList) {
        // 3.根据用户的选项判断每个题目的分数
        List<QuestionContentDTO> questionContents = JSONUtil.toList(question.getQuestionContent(), QuestionContentDTO.class);
        // 3.1.判断用户答案数量和题目是否一致
        if (questionContents.size() != choices.size()) {
            throw new WarnException(ErrorCode.PARAMS_ERROR);
        }
        // 3.2合并优化
        int scoreSum = 0;
        for (int i = 0; i < questionContents.size(); i++) {
            QuestionContentDTO questionContent = questionContents.get(i);
            String answer = choices.get(i);
            for (QuestionContentDTO.Option option : questionContent.getOptions()) {
                if (option.getKey().equals(answer)) {
                    scoreSum += option.getScore();
                    break;
                }
            }
        }

        // 4.判断总分数在哪个得分区间
        ScoringResult result = new ScoringResult();
        for (ScoringResult scoringResult : scoringResultList) {
            result = scoringResult;
            if (scoringResult.getResultScoreRange() <= scoreSum) {
                break;
            }
        }
        ScoreAndScoringResultDTO scoreAndScoringResultDTO = new ScoreAndScoringResultDTO();
        scoreAndScoringResultDTO.setResultScore(scoreSum);
        scoreAndScoringResultDTO.setScoringResult(result);
        return scoreAndScoringResultDTO;
    }
}
